package plp.orientadaObjetos2.declaracao.classe;

import java.util.List;

import plp.expressions2.memory.VariavelJaDeclaradaException;
import plp.expressions2.memory.VariavelNaoDeclaradaException;
import plp.orientadaObjetos1.declaracao.classe.DecClasse;
import plp.orientadaObjetos1.excecao.declaracao.ClasseJaDeclaradaException;
import plp.orientadaObjetos1.excecao.declaracao.ClasseNaoDeclaradaException;
import plp.orientadaObjetos1.excecao.declaracao.ProcedimentoJaDeclaradoException;
import plp.orientadaObjetos1.excecao.declaracao.ProcedimentoNaoDeclaradoException;
import plp.orientadaObjetos1.expressao.leftExpression.Id;
import plp.orientadaObjetos1.memoria.AmbienteCompilacaoOO1;
import plp.orientadaObjetos1.memoria.AmbienteExecucaoOO1;
import plp.orientadaObjetos2.declaracao.funcao.DecFuncao;
import plp.orientadaObjetos2.memoria.DefClasseOO2;
import plp.orientadaObjetos2.memoria.FuncaoJaDeclaradaException;

public class DecClasseNativa implements DecClasse{

	private Id nome;

	private List<DecFuncao> funcoesNativas;


	public DecClasseNativa(Id nome, List<DecFuncao> funcoesNativas) {
		super();
		this.nome = nome;
		this.funcoesNativas = funcoesNativas;
	}

	@Override
	public AmbienteExecucaoOO1 elabora(AmbienteExecucaoOO1 ambiente)
			throws VariavelJaDeclaradaException, VariavelNaoDeclaradaException,
			ClasseJaDeclaradaException, ClasseNaoDeclaradaException,
			ProcedimentoNaoDeclaradoException, ProcedimentoJaDeclaradoException {
		ambiente.mapDefClasse(this.nome, new DefClasseOO2(this.nome, null, null, null, null,
															this.funcoesNativas, true));
		return ambiente;
	}

	@Override
	public boolean checaTipo(AmbienteCompilacaoOO1 ambiente)
			throws VariavelJaDeclaradaException, VariavelNaoDeclaradaException,
			ClasseJaDeclaradaException, ClasseNaoDeclaradaException,
			ProcedimentoNaoDeclaradoException, ProcedimentoJaDeclaradoException {
		boolean tipoOk = true;
		List<DecFuncao> funcoes = this.funcoesNativas;
		ambiente.mapDefClasse(this.nome, new DefClasseOO2(this.nome, null, null, null,
															null, this.funcoesNativas, true));
		ambiente.incrementa();
		for (DecFuncao decFuncao : funcoes) {
			try {
				tipoOk &= decFuncao.checaTipo(ambiente);
			} catch (FuncaoJaDeclaradaException e) {
				tipoOk = false;
			}
		}
		ambiente.restaura();
		return tipoOk;
	}

}
